package io.huaguoguo;

import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.*;

/**
 * @Title:
 * @Description:
 * @author: huaguoguo
 * @Date： 2021/5/1 23:41
 */
public class SimpleTests {


    @Test
    public void test3() {
        int a = 17;
        int b = 3;
        a ^= b;
        b = a ^ b;
        a = a ^ b;
        System.out.println(a + "  ");
        System.out.println(b);
        // 00010001
        // 00000101
        System.out.println(17 ^ 3);
    }

    class MyData {
        public volatile int a = 0;

        public void add0() {
            a++;
        }

        public synchronized void add1() {
            a++;
        }
    }

    /**
     * volatile的可见性测试
     */
    @Test
    public void test4() {
        MyData myData = new MyData();
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "启动");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            myData.a = 60;
            System.out.println(Thread.currentThread().getName() + "完成");
        }, "aaa").start();

        System.out.println("主线程等待中");
        while (myData.a == 0) {

        }
        System.out.println("a更新，结束等待");
    }

    /**
     * volatile的非原子性测试
     */
    @Test
    public void test5() throws InterruptedException {
        int forI = 10000;
        MyData myData = new MyData();
        CountDownLatch countDownLatch = new CountDownLatch(forI);
        ExecutorService threadPool = Executors.newFixedThreadPool(forI);
        long start = System.currentTimeMillis();
        for (int i = 0; i < forI; i++) {
            threadPool.execute(() -> {
                myData.add1();
                countDownLatch.countDown();
            });
        }

        countDownLatch.await();
        long end = System.currentTimeMillis();
        System.out.println("完成后的a=" + myData.a);
        System.out.println("耗时：" + (end - start) + "ms");
        // add0 = 2047ms  add1 = 2063ms
    }


    /**
     * callback
     */
    @Test
    public void test6() throws ExecutionException, InterruptedException {

        FutureTask<Integer> task = new FutureTask<>(() -> 1024);
        new Thread(task).start();
        Integer integer = task.get();
        System.out.println(integer);

    }

    @Test
    public void test7() {
        ExecutorService threadExecutor = Executors.newSingleThreadExecutor();

        ThreadPoolExecutor pool = new ThreadPoolExecutor(12,
                24,
                1L,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1024),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        pool.execute(() -> {
            System.out.println(111);
        });
    }

    @Test
    public void test8() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5000L);
    }

    /**
     * 测试OOM
     */
    @Test
    public void test9() {
        String str = "";
        while (true) {
            str += str + UUID.randomUUID().toString();
        }
    }

    /**
     * unable to create new native thread
     */
    @Test
    public void test10() throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(1024 * 1024 * 1024);
        while (true) {
            executorService.execute(() -> {
                try {
                    System.out.println(executorService.toString());
                    TimeUnit.SECONDS.sleep(1L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

    }

    /**
     * MateSpace OOM
     */
    @Test
    public void test11() {
        int count = 0;
        try {
            while (true) {
                count++;
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(SimpleTests.class);
                enhancer.setCallback(new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        return methodProxy.invoke(o, objects);
                    }
                });
                enhancer.create();
            }
        } catch (Throwable e) {
            System.out.println(count + "次后，终于OOM了");
            e.printStackTrace();
        }


    }

    /**
     * 测试arrayList ensureCapacity方法
     * ensureCapacity前： 391ms
     * ensureCapacity后： 310ms
     */
    @Test
    public void test12() {
        ArrayList<Integer> list = new ArrayList<>();
        int n = 10000000;
//        list.ensureCapacity(n);
        for (int i = 0; i < n; i++) {
            list.add(i);
        }
    }

    @Test
    public void quickSortTest() {
        int[] a = {72, 6, 57, 88, 60, 42, 83, 73, 48, 85};
        quickSort(a, 0, a.length - 1);
        System.out.println(Arrays.toString(a));



    }

    public void quickSort(int[] a, int i, int j) {
        if (i == j) {
            return;
        }
        int mid = adjustArray(a, i, j);
        if (mid > i) {
            quickSort(a, i, mid-1);
        }
        if (mid < j) {
            quickSort(a, mid+1, j);
        }
    }

    private int adjustArray(int[] a, int i, int j) {
        int x = a[i];
        while (i < j) {
            // 从右往左，把小的埋到左边去
            while (i < j && a[j] > x) {
                j--;
            }
            if (i < j) {
                a[i++] = a[j];
            }
            // 从左往右，把大的埋到右边去
            while (i < j && a[i] < x) {
                i++;
            }
            if (i < j) {
                a[j--] = a[i];
            }
        }
        a[i] = x;
        return i;
    }

    @Test
    public void test13() {
//        [6, 42, 48, 57, 60, 72, 73, 83, 85, 88]
        int[] a = {72, 6, 57, 88, 60, 42, 83, 73, 48, 85};
        System.out.println(adjustArray(a, 3, a.length - 1));
    }

    @Test
    public void test14() throws InterruptedException {

        ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
        Queue<String> links = new LinkedList<>();
        for (int i = 0; i < 10; i++) {
            links.offer(UUID.randomUUID().toString());
        }

        new Thread(() ->{
            while (true) {
                try {
                    String value = links.poll();
                    if (value == null) {
                        break;
                    }
                    queue.put(value);
                    System.out.println("生产:" + value);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(() ->{
            while (true) {
                try {
                    String value = queue.take();
                    System.out.println("消费：" + value);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        TimeUnit.SECONDS.sleep(10L);
    }

    @Test
    public void test15() throws ExecutionException, InterruptedException {
        FutureTask<Integer> task = new FutureTask<>(() -> 111);
        task.run();
        System.out.println(task.get());
    }

    /**
     * cpu高占用测试，配置arthas查找原因
     * @throws InterruptedException
     */
    @Test
    public void test16() throws InterruptedException {
        new Thread(() -> {
            while (true) {

            }
        },"aaa").start();
        TimeUnit.SECONDS.sleep(500L);
    }
}
